<?php

use Phalcon\Mvc\Dispatcher;
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Php as PhpEngine;
use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Mvc\View\Engine\Volt as VoltEngine;
use Phalcon\Mvc\Model\Metadata\Memory as MetaDataAdapter;
use Phalcon\Flash\Direct as Flash;
use Phalcon\Flash\Session as FlashSession;
use Phalcon\Crypt;
use Phalcon\Http\Response\Cookies;
use Phalcon\Logger\Adapter\File as FileLogger;
use Phalcon\Cache\Frontend\Data as FrontData;
use Phalcon\Security;
use Phalcon\Logger\Adapter\Stream as StreamAdapter;
use Phalcon\Logger\Multiple as MultipleStream;
use Phalcon\Logger\Adapter\File as FileAdapter;
use Phalcon\Logger\Formatter\Line as FormatterLine;
use Phalcon\Mvc\Router;
use Phalcon\Mvc\Model\Manager as ModelManager;
use Phalcon\Mvc\Model\Transaction\Manager as TransactionManager;
use Phalcon\Security\Random;

/**
 * 创建一个默认的依赖注入容器
 */
$di = new Phalcon\Di\FactoryDefault();


/**
 * Shared configuration service
 */
$di->setShared('config', function () {


    $configArray = include BASE_PATH . '/config/config.php';

    $config = new \Phalcon\Config($configArray);

    $iniConfigPath = BASE_PATH . '/.env';

    //支持文件配置
    if(file_exists($iniConfigPath)){
        $ini = new Phalcon\Config\Adapter\Ini($iniConfigPath);
        if($ini->count() > 0){
            $config->merge(new \Phalcon\Config($ini->toArray()));
        }
    }

    return $config;
});

$config = $di->getShared('config');


/**
 * The URL component is used to generate all kind of urls in the application
 */
$di->setShared('url', function () use($config) {

    $url = new UrlResolver();
    if(isset($config->app->baseUri)){
        $url->setBaseUri($config->app->baseUri);
    }else{
        $url->setBaseUri(base_uri());
    }

    if(isset($config->app->staticUri)){
        $url->setStaticBaseUri($config->app->staticUri);
    }else{
        $url->setStaticBaseUri(base_uri());
    }

    $url->setBasePath(BASE_PATH . '/');

    return $url;
});

/**
 * Setting up the view component
 */
$di->setShared('view', function ()use($config) {

    $view = new View();
    $view->setDI($this);
    $view->setViewsDir($config->app->viewsDir);
    @mkdir($config->app->cacheDir,0666,true);
    @mkdir($config->app->compiledPath);

    $view->registerEngines([
        '.volt' => function ($view)use($config) {

            $volt = new VoltEngine($view, $this);

            $volt->setOptions([
                'compiledPath'      => $config->app->compiledPath,
                'compiledSeparator' => '_',
                'compileAlways'     => $config->app->viewCompileAlways,
                'compiledExtension' => $config->app->compiledExtension,
            ]);
            //自定义注入函数
            $compiler = $volt->getCompiler();
            $compiler->addFunction('in_array', 'in_array');
            $compiler->addFunction('isset','isset');
            $compiler->addFunction('empty','empty');
            $compiler->addFunction('convert_pay_name','convert_pay_name');
            $compiler->addFunction('convert_pay_gateway','convert_pay_gateway');

            return $volt;
        },
        '.phtml' => PhpEngine::class

    ]);

    return $view;
});

/**
 * Database connection is created based in the parameters defined in the configuration file
 */
$di->setShared('db', function () use($config) {

    $dbConfig = $config->database->default;

    $connection = new \Phalcon\Db\Adapter\Pdo\Mysql($dbConfig->toArray());
    @mkdir(RUNTIME_PATH . '/logs/');
    $eventsManager = new EventsManager();
    $connection->setEventsManager($eventsManager);
    $logger = new FileLogger(RUNTIME_PATH . '/logs/mysql.log');
    $eventsManager->attach("dbRead:beforeQuery",function($event,$connection)use($logger){
        $logger->log($connection->getSQLStatement(),\Phalcon\Logger::INFO);
    });

    return $connection;
});

/**
 * If the configuration specify the use of metadata adapter use it or use memory otherwise
 */
$di->setShared('modelsMetadata', function () {
    return new MetaDataAdapter();
});

$di->setShared('modelsManager',function (){
    return new ModelManager();
});

$di->setShared('transactionManager',function (){
    $transactionManager =  new TransactionManager();

    return $transactionManager;
});
/**
 * Register the session flash service with the Twitter Bootstrap classes
 */
$di->setShared('flash', function () {
    return new Flash([
        'error'   => 'alert alert-danger',
        'success' => 'alert alert-success',
        'notice'  => 'alert alert-info',
        'warning' => 'alert alert-warning'
    ]);
});
$di->setShared('flashSession',function (){

    $flash =  new FlashSession([
        'error'   => 'alert alert-danger alert-dismissible',
        'success' => 'alert alert-success alert-dismissible',
        'notice'  => 'alert alert-info alert-dismissible',
        'warning' => 'alert alert-warning alert-dismissible'
    ]);

    return $flash;
});

/**
 * Start the session the first time some component request the session service
 */
$di->setShared('session', function () use($config) {

    $sessionConfig = $config->session->default->toArray();

    if(isset($sessionConfig['auth']) && empty($sessionConfig['auth'])){
        unset($sessionConfig['auth']);
    }
    $session = new Phalcon\Session\Adapter\Redis($sessionConfig);

    $session->start();
    return $session;

});

$di->setShared('cookies', function (){
    $cookies = new Cookies();
    $cookies->useEncryption(true);
    return $cookies;
});

// 注册加密组件
$di->setShared('crypt', function () use ($config) {
    $crypt = new Crypt();
    $crypt->setPadding(\Phalcon\Crypt::PADDING_ZERO);
    if(isset($config->app->cryptEncode)) {
        // 设置全局加密密钥
        $crypt->setKey($config->app->cryptEncode);
    }
    return $crypt;
});

$di->setShared('cache', function ()use($config){
    $frontCache = new FrontData(
        [
            "lifetime" => $config->cache->lifetime ? $config->cache->lifetime : 172800,
        ]
    );

    $options = $config->cache->default;

    if(isset($options['auth']) && empty($options['auth'])){
        unset($options['auth']);
    }

    $cache = new Phalcon\Cache\Backend\Redis($frontCache,$options);
    
    return $cache;
});

$di->setShared("security", function () {
    $security = new Security();

    // Set the password hashing factor to 12 rounds
    $security->setWorkFactor(12);

    return $security;
});

//日志适配器
$di->setShared('log',function (){
    // 发送消息到stderr
    $logger = new MultipleStream();

    $file_path = RUNTIME_PATH . "/logs/access.log";
    @mkdir(dirname($file_path),0666,true);

    $file = new FileAdapter($file_path);
    $formatter = new FormatterLine(null,'Y-m-d H:i:s');

    $file->setFormatter($formatter);

    $logger->push($file);
    $logger->push(new StreamAdapter("php://stderr"));

    $syslog = new \Phalcon\Logger\Adapter\Syslog('Phalcon',[
        "option"   => LOG_NDELAY,
        "facility" => LOG_LOCAL2,
        ]);


    $logger->push($syslog);
    return $logger;

});
/**
 * 注入 redis 服务器
 */
$di->setShared('redis',function () use($config) {

    if (!isset($config->redis)) {
        throw new \Exception('没有配置 Redis 服务器');
    }
    if(!class_exists('\Redis')){
        throw new \Exception('Redis 类不存在');
    }
    $redisConfig = $config->redis->default;

    $redis = new \Redis();

    if(isset($redisConfig->persistent) && $redisConfig->persistent) {
        $redis->pconnect($redisConfig->host,intval($redisConfig->port));
    }else{
        $redis->connect($redisConfig->host,intval($redisConfig->port),300);
    }

    if(isset($redisConfig->auth) && empty($redisConfig->auth) === false) {
        $redis->auth($redisConfig->auth);
    }

    if(isset($redisConfig->igbinary) && $redisConfig->igbinary){
         $redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_IGBINARY);
    }

    $redis->setOption(\Redis::OPT_READ_TIMEOUT,-1);

    if(isset($redisConfig->index)){
        $redis->select(intval($redisConfig->index));
    }
    if(isset($redisConfig->prefix)){
        $redis->setOption(\Redis::OPT_PREFIX,$redisConfig->prefix);
    }

    return $redis;
});

$di->setShared('router',function (){

    $router = require_once (BASE_PATH . '/config/routers.php');

    if(empty($router)){
        $router = new Router();
    }

    return $router;
});


$di->setShared('filter',function (){
    $filter = new Phalcon\Filter();

    $filter->add('ipv4',function ($value){
        return  filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
    });
    return $filter;
});

$di->setShared('loader', function () use ($loader) {
    return $loader;
});

/**
 * 注入随机数
 */
$di->setShared('random',function (){
   $random = new Random();

   return $random;
});


$di->setShared("dispatcher", function () {

    $eventsManager = new EventsManager;

    $dispatcher = new Dispatcher();

    $dispatcher->setEventsManager($eventsManager);
    $dispatcher->setDefaultNamespace('Cohuna\Controllers');
    $dispatcher->setDefaultController('Merchant');


    return $dispatcher;
});